package main

import (
	"fmt"
	"github.com/dop251/goja"
	"golang.org/x/sync/errgroup"
	"log"
	"sync"
	"unsafe"
)

func Pgoja(c int) {
	params := createParams()

	vm := goja.New()
	program, err := goja.Compile("", example, false)
	if err != nil {
		log.Fatal(err)
	}

	vm.Set("Origin", params["Origin"])
	vm.Set("Country", params["Country"])
	vm.Set("Adults", params["Adults"])
	vm.Set("Value", params["Value"])

	var out goja.Value

	for n := 0; n < c; n++ {
		out, err = vm.RunProgram(program)
	}

	if err != nil {
		log.Fatal(err)
	}
	if !out.ToBoolean() {
		log.Println("result error")
	}
}

func OneGoja(bs []byte) error {
	params := createParams()

	vm := goja.New()

	vm.Set("Origin", params["Origin"])
	vm.Set("Country", params["Country"])
	vm.Set("Adults", params["Adults"])
	vm.Set("Value", params["Value"])

	var out goja.Value
	var program *goja.Program = *(**goja.Program)(unsafe.Pointer(&bs))

	//log.Printf("3====%v\n", program)

	out, err := vm.RunProgram(program)

	if err != nil {
		log.Printf("4=====%v\n", err)
		return err
	}
	if !out.ToBoolean() {
		log.Println("result error")
		return err
	}
	return nil
}

type SliceMock struct {
	addr uintptr
	len  int
	cap  int
}

func BatchGoja(c int) {
	g := new(errgroup.Group)
	program, err := goja.Compile("", example, false)
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("5=====%v\n", program)

	Len := unsafe.Sizeof(*program)
	testBytes := &SliceMock{
		addr: uintptr(unsafe.Pointer(program)),
		cap:  int(Len),
		len:  int(Len),
	}
	data := *(*[]byte)(unsafe.Pointer(testBytes))
	fmt.Println("[]byte is : ", data)
	//log.Printf("7=====%v\n", hex.EncodeToString(ptestStruct))
	var ptestStruct *goja.Program = *(**goja.Program)(unsafe.Pointer(&data))

	log.Printf("6=====%v\n", ptestStruct)
	//log.Printf("8====%v\n", pr)

	for n := 0; n < c; n++ {
		g.Go(func() error {
			err := OneGoja(data)
			return err
		})
	}
	if err := g.Wait(); err != nil {
		log.Println("Get errors: ", err)
	} else {
		log.Println("Get all num successfully!")
	}
}

func BatchGoja1(c int) {
	var wg sync.WaitGroup
	program, err := goja.Compile("", example, false)
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("5=====%v\n", program)

	Len := unsafe.Sizeof(*program)
	testBytes := &SliceMock{
		addr: uintptr(unsafe.Pointer(program)),
		cap:  int(Len),
		len:  int(Len),
	}
	data := *(*[]byte)(unsafe.Pointer(testBytes))
	fmt.Println("[]byte is : ", data)
	//log.Printf("7=====%v\n", hex.EncodeToString(ptestStruct))
	var ptestStruct *goja.Program = *(**goja.Program)(unsafe.Pointer(&data))

	log.Printf("6=====%v\n", ptestStruct)
	//log.Printf("8====%v\n", pr)

	for n := 0; n < c; n++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			err := OneGoja(data)
			if err != nil {
				log.Printf("OneGoja error:%v\n", err)
			}
		}()
	}
	wg.Wait()
	log.Println("Get all num successfully!")
}
